package com.tanhua.server.service;

import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.constant.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.VideoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 小视频业务处理层逻辑
 */
@Slf4j
@Service
public class SmallVideoService {

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FastFileStorageClient client;//文件上传客户端对象 /group1/M00/00/00/wKiIoGG_9YCACIIaAATPmhnHJ_s286.png

    @Autowired
    private FdfsWebServer fdfsWebServer; //获取 http://192.168.136.160:8888/路径


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    /**
     * 视频发布
     *
     * @param videoThumbnail 视频封面文件
     * @param videoFile      视频文件
     * @return
     */
    public void publish(MultipartFile videoThumbnail, MultipartFile videoFile) {
        try {
            Video video = new Video();
            Long userId = UserHolder.getUserId();
            //1.获取当前登录用户id 设置为视频作者id
            video.setUserId(userId);
            //2.视频发布的文字
            video.setText("你喜欢黑丝吗");
            //3.获取视频封面图片地址
            String filename = videoThumbnail.getOriginalFilename();//获取视频封面原始文件名称
            String picUrl = ossTemplate.upload(filename, videoThumbnail.getInputStream());
            video.setPicUrl(picUrl);
            //4.获取视频地址
            String suffix = videoFile.getOriginalFilename().substring(videoFile.getOriginalFilename().lastIndexOf(".") + 1); //.mp4 ==> mp4
            StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
            String videoUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
            video.setVideoUrl(videoUrl);
            //5.调用服务保存视频
            videoApi.add(video);
            log.debug("*****************视频发布成功了*****************");
        } catch (IOException e) {
            log.debug("*****************视频失败了*****************");
            throw new TanHuaException(ErrorResult.error());
        }
    }

    /**
     * 视频列表分页查询（推荐系统视频数据==>视频表分页查询）
     * vids=100个
     * page = 1 pagesize=10
     * page = 12 pagesize=10
     * key=当前用户id_1_10 #page #pagesize
     */
    @Cacheable(value = "videos",key = "T(com.tanhua.server.interceptor.UserHolder).userId + '_' + #page + '_' +#pagesize")
    public PageResult<VideoVo> findPage(Long page, Long pagesize) {
        //1根据key查询redis中Vids是否存在
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        String vids = stringRedisTemplate.opsForValue().get(key);//推荐使用的vids
        Long counts=0l;//总记录数
        Long redisPage=0l;//redis总页码
        List<Video> videoList = new ArrayList();
        //2存在 分页查询 调用服务提供者获取推荐视频列表数据
        if (StringUtils.isNotEmpty(vids)) {
            String[] vidsArr = vids.split(",");//得到视频数组 100个vid 分页得到10个id
            long start = (page - 1) * pagesize;//开始哪条开始查询
            counts = Long.valueOf(vidsArr.length);
            redisPage = (long) PageUtil.totalPage(counts.intValue(), pagesize.intValue()); //10页
            if (counts > start) {
                List<Long> listVids = Arrays.stream(vidsArr).skip(start).limit(pagesize).map(v -> Long.valueOf(v)).collect(Collectors.toList());
                videoList = videoApi.findByVids(listVids);
            }
        }
        //3不存在 直接从数据库直接分页查询视频数据
        if (CollectionUtils.isEmpty(videoList)) {
            PageResult<Video> pageResult = videoApi.findPage(page - redisPage, pagesize);
            videoList = pageResult.getItems();
            counts = pageResult.getCounts();
        }
        List<VideoVo> videoVoList = new ArrayList();
        if(!CollectionUtils.isEmpty(videoList)) {
            //4.获取出所有视频作者ids
            List<Long> listUserIds = videoList.stream().map(Video::getUserId).collect(Collectors.toList());
            //5.根据视频作者ids获取视频作者详情
            Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(listUserIds, null);
            //6.基于视频作者详情  与 视频对象 构造VideVo返回
            for (Video video : videoList) {
                videoVoList.add(VideoVo.init(userInfoMap.get(video.getUserId()),video));
            }
        }
        return new PageResult<>(page,pagesize,counts,videoVoList);
    }
}
